You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Use handle-based text overwrites in FileHelper - #5353
Use anchored directories and opened file descriptors for FileHelper.overwrite_text() while retaining its non-atomic text-upsert contract. Preserve supported contained symlink chains, trusted root aliases, existing inode and hard-link identity, permissions, and native text encoding and newline behavior.
Extract the existing Windows handle primitive into a shared private module, add overwrite coverage, and document the operation's filesystem behavior and limitations. This is an independent change targeting main, not a stacked PR.
Testing
Set up this checkout's .venv and editable install using the local development guide. Run commands from the checkout root.
Tested locally with .venv/bin/specify --help (Windows PowerShell: .\.venv\Scripts\specify.exe --help)
Ran relevant existing tests with .venv/bin/python -m pytest tests -q (Windows PowerShell: .\.venv\Scripts\python.exe -m pytest tests -q); use affected test paths for focused checks and LC_ALL=en_US.UTF-8 on macOS
Validation ran on macOS. Native Windows tests are included but were not executed on this host. A separate sample-project run is not applicable; operation tests use temporary project roots. The full test suite was not run.
AI Disclosure
I did not use AI assistance for this contribution
I did use AI assistance (fill in the disclosure below)
AI disclosure: GitHub Copilot using GPT-6.1 Sol (model ID: gpt-6.1-sol) in autonomous mode with runtime-default reasoning settings authored the implementation, tests, documentation, commit message, and PR description, and ran local validation on behalf of @mnriem.
Use the Darwin kernel search bit when Python does not expose O_SEARCH or O_PATH, and exercise the missing-constant branch for existing and new overwrite destinations.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Concurrent Windows overwrites can corrupt the process-wide umask, POSIX traversal can exhaust file descriptors, and the Windows regression test can fail because it compares different encodings.
Close previous POSIX directory FDs during traversal
src/specify_cli/file_helper.py:267
Keeping every POSIX ancestor in the ExitStack makes descriptor usage grow with path depth, although only the current directory FD is needed for anchored traversal. With 80 valid parent directories and RLIMIT_NOFILE=64, native text overwrite succeeds but this implementation raises EMFILE before opening the leaf. Please close each previous parent after opening its child, as _cache_directory already does; retain the full hierarchy only on Windows, where the sharing locks require it.
Remove the blanket overwrite_text sandbox exception
design/file-helper.md:227
The blanket overwrite_text exception implies a race-free sandbox and excludes its writes from the partial-results warning. That conflicts with its write-failure contract at lines 180–182 and namespace limits at lines 242–246. Remove this exception and keep the narrower anchored-traversal guarantee in the operation's description above.
Let exclusive CRT creation apply Windows creation masks while retaining anchored existing-file opens. Close previous POSIX directory descriptors during traversal and clarify overwrite limitations. Cover interleaved calls, deep paths under low descriptor limits, and Windows creation collisions.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Overlapping overwrites can corrupt the Windows runtime permission mask, while directory pins unnecessarily require listing access and block otherwise permitted writes.
Overlapping overwrites corrupt the process creation mask
src/specify_cli/_file_handles.py:46
Two overlapping overwrites can restore 0o200 over an original mask of 0, making a newly created file read-only and changing permissions for later file creations. Unrelated native text-file creation can also observe the temporary mask between these calls. Use a creation strategy that applies the Windows runtime's mask without mutating it, and add an overlapping-call regression; a helper-only lock would not protect unrelated file creators.
Directory pins incorrectly require list access
src/specify_cli/file_helper.py:239
The reused _windows_handle(..., directory=True) requests FILE_LIST_DIRECTORY for every directory it pins. On Windows, a directory can allow traversal and writes to a known child while denying directory listing, so this now raises PermissionError for files that native Path.write_text() and the previous implementation can overwrite. Please use directory pins that require traversal rather than listing access while retaining rename protection, and add a native Windows ACL parity regression.
Capture masked Windows creation attributes with an empty private probe in the pinned parent, then exclusively create the destination through a no-follow native handle. Clean up the probe, preserve existing in-place updates, and cover leaf collisions during attribute capture.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The Windows permission probe can fail when creation and writing are allowed but deletion is denied, leaving a probe file behind and aborting otherwise permitted destination creation.
Resolve shared handle and filesystem contract conflicts while retaining the upstream exclusive-creation implementation and both test suites.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Deny the advanced DE and DC rights explicitly and confirm ordinary file reading remains available before exercising overwrite behavior.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
The overwrite documentation omits Windows pinning’s directory-listing and attribute-read requirements on the canonical root and resolved parents, leaving unexplained why restrictive access rules can prevent overwriting an otherwise writable file.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The overwrite contract omits the new Windows directory-list access requirement on the root and parent directories, leaving a platform-specific failure mode undocumented.
State that the canonical root and every resolved parent require directory-list and read-attributes access, including the resulting failure when an ACL allows file writes but denies listing.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Exercise leaf replacement with a no-reader FIFO in timeout-bounded subprocesses for both link policies. Require the nonblocking ENXIO failure and preserve the original file contents while retaining reader-present file-type coverage.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
Human review is needed to assess test coverage gaps around unsupported platform primitives, concurrent file creation, and creation-mask probe avoidance during Windows overwrites.
Updated in 032dad0d: the concurrency test now runs two overwrite calls and relies on the existing assertion that os.umask must not be called, with no simulated mask state or timed waits. It still checks descriptor cleanup. .venv/bin/python -m pytest tests/test_file_handles.py tests/test_file_helper.py::test_overwrite_text_io_errors_propagate -q passed (38 tests). GitHub Copilot (GPT-6.1 Sol, gpt-6.1-sol, autonomous; reasoning setting not exposed) generated this test change, ran validation, and wrote this comment on behalf of @mnriem.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
The new Win32/CRT filesystem paths lack native Windows validation, and macOS-only runs with portable mocks cannot establish sharing, ACL, creation-mask, or handle-ownership behavior.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
triage-must-haveVerdict: high-value, important work for Spec Kit — do first
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Use anchored directories and opened file descriptors for
FileHelper.overwrite_text()while retaining its non-atomic text-upsert contract. Preserve supported contained symlink chains, trusted root aliases, existing inode and hard-link identity, permissions, and native text encoding and newline behavior.Extract the existing Windows handle primitive into a shared private module, add overwrite coverage, and document the operation's filesystem behavior and limitations. This is an independent change targeting
main, not a stacked PR.Testing
Set up this checkout's
.venvand editable install using the local development guide. Run commands from the checkout root..venv/bin/specify --help(Windows PowerShell:.\.venv\Scripts\specify.exe --help).venv/bin/python -m pytest tests -q(Windows PowerShell:.\.venv\Scripts\python.exe -m pytest tests -q); use affected test paths for focused checks andLC_ALL=en_US.UTF-8on macOSCommands and results:
.venv/bin/specify --help— passed.LC_ALL=en_US.UTF-8 .venv/bin/python -m pytest tests/test_file_helper.py tests/test_file_helper_overwrite.py tests/test_file_handles.py tests/specify_cli/workflows/test_catalog_cache.py tests/specify_cli/test_file_policy.py tests/integrations/test_integration_state.py -q— 489 passed, 88 skipped.git diff --check— passed.Validation ran on macOS. Native Windows tests are included but were not executed on this host. A separate sample-project run is not applicable; operation tests use temporary project roots. The full test suite was not run.
AI Disclosure
AI disclosure: GitHub Copilot using GPT-6.1 Sol (model ID:
gpt-6.1-sol) in autonomous mode with runtime-default reasoning settings authored the implementation, tests, documentation, commit message, and PR description, and ran local validation on behalf of @mnriem.